#include <iostream>
#include "Sock.hpp"
#include "HttpServer.hpp"
#include <memory>
#include <string>
#include "Util.hpp"
#include <vector>
#define SEP "\n" //"\r\n"
using namespace std;
static const string webroot = "./wwwroot";          // web根目录
static const string defaultHomePage = "index.html"; // 默认首页
static const string defaultErrPage = "./wwwroot/Error.html";  // 默认错误首页

struct HttpRequest
{
    HttpRequest()
        : _url(webroot)
    {
    }

    string _method;//请求方法
    string _url;//请求url
    string _version;//版本
    vector<string> _header;//请求报头
    string _suffix;//读取文件后缀
    string body;//正文
};

// 对http请求进行反序列化
HttpRequest HttpDeserialization(string &request)
{

    HttpRequest req;
    string requestline = Split(request, SEP);                  // 先把请求行切出来
    Analyze(requestline, req._method, req._url, req._version); // 解析请求行
        string line;
    while (line!="error")
    {
        // cout<<request<<endl;
        line = Split(request, SEP);
        req._header.push_back(line);
    }
    req.body=request;
    req._header.erase(--req._header.end());//把最后的error删除
    req._header.erase(--req._header.end());//把最后第二个空字符串删除
    return req;
}

void Print(const HttpRequest &req)
{
    cout << "------------------------------------------------------------------" << endl;
    cout << "以下为请求报文:" << endl;
    cout << "methods:" << req._method << endl;
    cout << "url:" << req._url << endl;
    cout << "version:" << req._version << endl;
    for (auto &e : req._header)
    {
        cout << e << endl;
    }
    cout<<"正文:"<<req.body<<endl;
    cout << "------------------------------------------------------------------" << endl;
}

// 接下来的两个函数是为了找出要访问文件的后缀，并添加到响应报头中去
// 找出文件后缀
void FileSuffixJudge(string &filename, string &suffix)
{
    size_t pos = filename.rfind('.');
    if (pos == string::npos)
    {
        suffix = "";
    }
    else
    {
        suffix = filename.substr(pos);
    }
}

string CheckType(string &suffix) // 通过后缀选出content-type
{
    if (suffix == ".html")
    {
        return "text/html";
    }
    else if (suffix == ".jpg")
    {
        return "application/x-jpg";
    }
    else if (suffix == "jpeg")
    {
        return "image/jpeg";
    }
    else if (suffix == ".png")
        return "image/png";
    else
    {
        return "";
    }
}

string HandlerHttp(string &request)
{

    HttpRequest req = HttpDeserialization(request);
    // 检查内容
    Print(req);
    if (req._url[req._url.size() - 1] == '/')
    {
        LogMessage(Debug, "要访问的是首页");
        req._url += defaultHomePage;
    }

    // 读取文件,准备响应给客户端
    string filecontent;
    cout << "读取的文件名:" << req._url << endl;
    bool flag = ReadFile(req._url, filecontent);

    string content_type;
    if (flag)
    {
        // 选出  Content-Type
        FileSuffixJudge(req._url, req._suffix);
        content_type= CheckType(req._suffix);
    }
    else
    {
        content_type=".html";
    }

    if(flag)
    {
        LogMessage(Debug,"200 OK");
    // 整合报头
    string response;
    // 状态行
    response += "HTTP/1.0 200 OK";
    response += SEP;
    // 响应报头
    response += "Content-Type:";
    response += content_type;
    response += SEP;
    response += "Content-Length:";
    response += to_string(filecontent.size());
    response += SEP;
    // 空行
    response += SEP;
    // 正文
    response += filecontent;

    return response;
    }
    else
    {
        LogMessage(Debug,"404 Not Found");
        //error读取文件失败的话返回404
        string response;
        response+="HTTP/1.0 404 Not Found";
        response+=SEP;
        response+=SEP;
        string filecontent;
        ReadFile(defaultErrPage,filecontent);
        response+=filecontent;
        return response;

    }

    // string response;
    // response+="HTTP/1.0 302 Redirect";
    // response+=SEP;
    // response+="Location:https://www.baidu.com/index.html";
    // response+=SEP;
    // response+="Set-Cookie:sessionid=lnbabcd";
    // response+=SEP;
    // response+=SEP;
    // return response;
}

void Usage() // 输入提示
{
    printf("Usage:\n\t./server serverport \n");
}

int main(int argc, char *argv[])
{

    if (argc != 2)
    {
        Usage();
        exit(USE_ERR);
    }

    shared_ptr<Server> ptr(new Server(atoi(argv[1]), HandlerHttp));
    ptr->Init();
    ptr->Start();
    return 0;
}